;(function(){
	bf.jsonPath = {
		childrenToken : 'children',
		// 输入 JSON，要求 Array， 不能 对象
		jsonArr : null,

		/**
	     * @return {Array}
	     */
	    toList : function(){
	    	if(!this.jsonArr)throw '未输入 JSON 数据！';

	        var result = [];
	        array_Iterator.Fn = function(e, arr, i, j){
	            result.push(e);
	        }
	        array_Iterator.childrenToken = this.childrenToken;
	        array_Iterator(this.jsonArr, result);

	        return result;
	    },

	    /**
	     * 获取第 N 级的数据，从 0 开始。
	     * @return {Object}
	     */
	    levelAt : function(level){
	    	if(!this.jsonArr)throw '未输入 JSON 数据！';

	        var result = [];
	        array_Iterator.Fn = function(e, arr, i, j){
	            if(j == level){
	                // assert every node has a key name called "id"
	                if(!this.fullPath)this.fullPath = ''; // 执行此步的时候为根目录
	                e.fullPath = this.fullPath + '/' + e.id;
	                result.push(e);
	            }
	        }
	        array_Iterator.childrenToken = this.childrenToken;
	        array_Iterator(this.jsonArr, result);

	        return result;
	    },

	    /**
	     * getHashValueByFullKey
	     * @param   {Boolean} isAllMatch
	     * @param   {String|Array}
	     * @return  {Object}
	     */
	    hashSearch : function(path){
	    	if(!this.jsonArr)throw '未输入 JSON 数据！';

	        if(!path)
	            throw '未输入参数！';
	        else if(arguments.length > 1)     // 可变参数的条件
	            path = Array.prototype.slice.call(arguments, 0);
	        else if(typeof path == 'string'){  // 送入字符串的条件
	            path = path.split('/');
	            path.shift();
	        }else if(path.pop){                 // 送入数组的条件
	            // do nothing...
	        }

	        var result = [], i = 0, withPathData = buildPath.call(this);

	        /**
	         * @param {String} key
	         */
	        (function(key){
	            var _shift = this[key];
	            if(!_shift)return;
	            
	            result.push(_shift);
	            arguments.callee.call(_shift, path[++i]);// 相当于 i++;var nextKey = path[i];arguments.callee.call(_shift, nextKey);
	        }).call(withPathData, path[i]);
	        
	        return result;
	    },

	    getNode : function(path){
	        var node = this.hashSearch.apply(this, arguments);
	        return node.pop ? node.pop() : null;
	    },  

	    /**
	     *  可编织任意的数据，如：      
	        var h = {};
	        var foo = this.webStructure.buildIndex(null, null, function(e, arr, i, j){
	            if(j == 1){
	                h[e.id] = e;
	            }
	        });
	     * @param {Array} arr
	     * @param {String} keyName 注意不是什么类型的数据都可以作为key！
	     * @param {Function} handler
	     * @return {Object}
	     */
	    buildIndex : function(arr, keyName, handler){
	        var hash;
	        
	        hash    = {};
	        arr     = arr       || this.jsonArr;
	        keyName = keyName   || 'id';  // assert every node has a key name called "id"
	        
	        array_Iterator.Fn = handler;
	        
	        array_Iterator(arr, hash);
	        
	        return hash;
	    }
	    , 
		makeSiteMap : function(appID){
			
			/**
			 * @private
			 * @type {String}
			 */
			var div		= '<div class="indentBlock indentBlock_{1}"><span class="dot">·</span>{0}</div>\n';
			
			var sitemap = '';
		    var z = 0, isSetted = false;
		    
		    buildPath.call(this);
		    
		    array_Iterator.Fn =  function (e, arr, i, j){ 
		    	// 忽略后台节点
		    	if(e.isHidden_fromFrontEnd){
		    		return false;
		    	}
				if(!this.fullPath)this.fullPath = ''; // 执行此步的时候为根目录
				// 包含父路径的全称路径
				var diver = e.isHashUrl ? '#' : '/'; 
				e.fullPath = this.fullPath + diver + e.id; 
				
				// 缩进
			
				var text = '<a href="{0}" class="indentBlock_{2}"><span class="dot">·</span>{1}</a>\n '.format(
						appID + e.fullPath, e.name, j
				);
				
				// 划分为两栏
				z++;
//				if((z > small && z < big) && !isSetted && j == 0){
				
				if(isSetted && j == 0){
					text = '\n\t<\/td>\n\t<td>\n\t\t' + text;
				}	
				if(!isSetted)isSetted = true;
		        sitemap += text;
		    }
		    
			array_Iterator(this.jsonArr, {});
			
			return '<table class="siteMap"><tr><td>\n\t' + sitemap + '\n\t<\/td><\/tr><\/table>';
		}
	};

	var undefinedStr = 'undefined';

	/**
	 * iterator
	 * @param {Array} arr
	 * @param {Object} scope 充分利用 JS 独有的 this 对象指针以确定函数作用域，收窄对象范围。
	 * @param {Number} i
	 * @param {Number} j A ghost value, 穿梭于
	 */
	function array_Iterator(arr, scope, i, j){
	    if(typeof scope == undefinedStr)scope = this;
	    if(typeof i == undefinedStr)i = 0;
	    if(typeof j == undefinedStr)j = 0;

	    var element = arr[i], 
	    /*	该函数为递归函数，以上参数随递归变化而不同，而下面
	    	此部分的参数相对“静态”，故透过 arg.callee 获取引用 */
	    	selfFn = arguments.callee;

	    if(typeof element == undefinedStr)return;

	    // do something...
	    if(selfFn.Fn && selfFn.Fn.call(scope, element, arr, i, j) == false)return;
	    // do something-End
	    
	    var children = element[selfFn.childrenToken];
	    if (children && children.length){
	        // -->y
	        selfFn(children, element/*已经变了这个Scope*/, 0, j + 1);// var x = j + 1; // 每一次循环children都会对j产生变化
	    };
	    // -->x
	    selfFn(arr, scope, ++i, j /* Do not give a "j" here, cause it's needed to have j reset!*/);    
	}

	// 除了构建路径 path 外，还会把子元素附加到父元素身上，以为 hash 查找之用
	function buildPath(){
		// 如果已经 build 过无须重复 build
		if(this.builded)return this.builded;
		
	    var hash = {};
	    array_Iterator.Fn = function(e, arr, i, j){
	        if(!this.fullPath)this.fullPath = '';	// 执行此步的时候为根目录
	        e.fullPath = this.fullPath + '/' + e.id;// 包含父路径的全称路径
	        e.sj = j; 								// 缩进
	        this[e.id] = e;							// 当前结构是，直接附加在对象身上。考虑分配一个专用的 key，或者 搜索 children？
	    }
	     
	    array_Iterator.childrenToken = this.childrenToken;
	    array_Iterator(this.jsonArr, hash);
	    
	    if(!this.builded) this.builded = hash;
	    
	    return hash;
	}
	

})();

bf.config = {
	/**
	 * 读取某个节点
	 * @param node
	 * @returns
	 */
	getStru : function(node, cfg){
		node = String(node);
		// #--> /
		node = node.replace('#', '/');
		
		node = (function(node){
			var arr = node.split('/'), last = arr.pop();
			// index.jsp 为本级节点所属，其他的为下一级
			if(last.indexOf('index.jsp') != -1){
			}else{
				node = arr.join('/');
				// e.g product.jsp --> product
				node += '/';
				node += last.split('.').shift();
				
			}
			return node;
		})(node);
		
		if(cfg && cfg.isFull){
			var arr = bf.jsonPath.hashSearch(node);
			
			if(cfg.isOutputMarkup){
				var markup = [],
					tpl = '<a href="{0}{fullPath}">{name}</a> '.format(cfg.root);
				for(var i = 0, j = arr.length; i < j; i++){
					markup.push(tpl.format(arr[i])); 
				} 
				return markup.join(' » ');
			}else{
				var java_arr = new java.util.ArrayList();
				
				for(var i = 0, j = arr.length; i < j; i++){
					java_arr.add(bf.java.toHashMap(arr[i]));
				}
				
				return java_arr;
			}
			

		}else{
			return bf.jsonPath.getNode(node);
		}
	},
	/**
	 * 生成导航
	 */
	getNav: function(){
		var arr = bf.jsonPath.levelAt(0);
		
		return bf.java.toArrayList(arr, true);
	}
};